Growth and Activation

join = read.csv("guild-activation.csv")
join

leave = read.csv("guild-leavers.csv")
leave

source = read.csv("guild-joins-by-source.csv")
source

Engagement by channels

text = read.csv("popular-text-channels.csv")
text

voice_channel = read.csv("popular-voice-channels.csv")
voice_channel

Message Activity

message = read.csv("guild-message-activity.csv")
message

voice = read.csv("guild-voice-activity.csv")
voice

communicator = read.csv("guild-communicators.csv")
communicator

ETL on Growth and Activation

messing around with date time

library

library(lubridate)

datetime example

I grabbed this example from astrostats.psu

## read in date/time info in format 'm/d/y h:m:s'
dates <- c("02/27/92", "02/27/92", "01/14/92", "02/28/92", "02/01/92")
times <- c("23:03:20", "22:29:56", "01:03:30", "18:21:03", "16:56:26")
x <- paste(dates, times)
strptime(x, "%m/%d/%y %H:%M:%S")
[1] "1992-02-27 23:03:20 CST" "1992-02-27 22:29:56 CST" "1992-01-14 01:03:30 CST" "1992-02-28 18:21:03 CST" "1992-02-01 16:56:26 CST"
strptime(x, "%m/")
[1] NA NA NA NA NA

tests to investigate how to extract date time

These were scuffed tests I used to learn how to extract the date time * the variable test made me realize removing +00:00 and replacing it with a Z would make the data in a format that can be read by R * the variable test2 was my attempt to try getting it for an entire column

test = "2021-03-27T00:00:00Z"
str(ymd_hms(test))
 POSIXct[1:1], format: "2021-03-27"
test2 = join$interval_start_timestamp
#test2
#ymd_hms(join$interval_start_timestamp)

#strptime(test2, "%Y-%m-%dT%H:%M:%SZ")

While performing my tests, I struggled understanding format of the date was in, a search of a 2021-03-27T00:00:00+00:00 datatype pointed me to a stack overflow page that helped me learn more about python functions Date Time Formats in Python.

testing substring removal

  • with a understanding of what I needed to make it possible, I moved on to learn about substring replacement. This took a long time to figure out and understand.

removing the plus sign

a search of R remove all text after plus sign helped me break through this barrier I found that this answer on stackoverflow was particularly helpful in removing the + sign How to remove + (plus sign) from string in R?

removing the rest of zeros

I found the following stackoverflow answer that had a example for how to remove the rest of a string Remove all text before colon

gsub("\\+.*", 'Z', "2021-03-27T00:00:00+00:00")
[1] "2021-03-27T00:00:00Z"

removing +00:00 from the whole column

these were tests I ran to automate this for all the datetime rows

#join[1,1] = gsub("\\+.*", 'Z', join[1,1])
#join

join[,1] = gsub("\\+.*", 'Z', join[,1])
join
NA

split the interval_start_timestamp

Once I got it working on a row, I applied what I learned above to extract the year, month, and day from the initial datetime object Later when I was generating the bar charts, I had issues ordering the data by calendar months, a quick search yielded Sorting months in R I learned that passing months into factor with the levels = month.name would allow me to sort by the months

year = year(as.POSIXlt(join$interval_start_timestamp))

month = factor(months(as.POSIXlt(join$interval_start_timestamp)),levels = month.name)

day = weekdays(as.POSIXlt(join$interval_start_timestamp))

make the new dataframe

After making the split dataframes, I used a cbind to append the columns to the original dataset and reordered the dataset.

joins = cbind(join, year, month,day)
joins

joins = joins[,c(1,5,6,7,2,3,4)]
joins

testing if I could change the months to become a factor

# test to see what would happen if I could convert a months output as a factor
factor(months(as.POSIXlt(join$interval_start_timestamp)),levels = month.name)
  [1] March     March     March     April     April     April     April     April     April     April     April     April     April     April    
 [15] April     April     April     April     April     April     April     April     April     April     April     April     April     April    
 [29] April     April     April     April     April     May       May       May       May       May       May       May       May       May      
 [43] May       May       May       May       May       May       May       May       May       May       May       May       May       May      
 [57] May       May       May       May       May       May       May       May       June      June      June      June      June      June     
 [71] June      June      June      June      June      June      June      June      June      June      June      June      June      June     
 [85] June      June      June      June      June      June      June      June      June      June      July      July      July      July     
 [99] July      July      July      July      July      July      July      July      July      July      July      July      July      July     
[113] July      July      July      July      July      July      July      July      July      July      July      July      July      August   
[127] August    August    August    August    August    August    August    August    August    August    August    August    August    August   
[141] August    August    August    August    August    August    August    August    August    August    August    August    August    August   
[155] August    August    September September September September September September September September September September September September
[169] September September September September September September September September September September September September September September
[183] September September September September October   October   October   October   October   October   October   October   October   October  
[197] October   October   October   October   October   October   October   October   October   October   October   October   October   October  
[211] October   October   October   October   October   October   October   November  November  November  November  November  November  November 
[225] November  November  November  November  November  November  November  November  November  November  November  November  November  November 
[239] November  November  November  November  November  November  November  November  November  December  December  December  December  December 
[253] December  December  December  December  December  December  December  December  December  December  December  December  December  December 
[267] December  December  December  December  December  December  December  December  December  December  December  December  January   January  
[281] January   January   January   January   January   January   January   January   January   January   January   January   January   January  
[295] January   January   January   January   January   January   January   January   January   January   January   January   January   January  
[309] January   February  February  February  February  February  February  February  February  February  February  February  February  February 
[323] February  February  February  February  February  February  February  February  February  February  February  February  February  February 
[337] February  February  March     March     March     March     March     March     March     March     March     March     March     March    
[351] March     March     March     March     March     March     March     March     March     March     March     March     March     March    
[365] March     March     March     March     March     April     April     April     April     April     April     April     April     April    
[379] April     April     April     April     April     April     April     April     April     April     April     April     April     April    
[393] April     April     April     April     April     April     April     May       May       May       May       May       May       May      
[407] May       May       May       May       May       May       May       May       May       May       May       May       May       May      
[421] May       May       May       May       May       May       May       May       May       May       June      June      June      June     
[435] June      June      June      June      June      June      June      June      June      June      June      June      June      June     
[449] June      June      June      June      June      June      June      June      June      June      June      June      July      July     
[463] July      July      July      July      July      July      July      July      July      July      July      July      July      July     
[477] July      July      July      July      July      July      July      July      July      July      July      July      July      July     
[491] July      August    August    August    August    August    August    August    August    August    August    August    August    August   
[505] August    August    August    August    August    August    August    August    August    August    August    August    August    August   
[519] August    August    August    August    September September September September September September September September September September
[533] September September September September September September September September September September September September September September
[547] September September September September September September October   October   October   October   October   October   October   October  
[561] October   October   October   October   October   October   October   October   October   October   October   October   October   October  
[575] October   October   October   October   October   October   October   October   October   November  November  November  November  November 
[589] November  November  November  November  November  November  November  November  November  November  November  November  November  November 
[603] November  November  November  November  November  November  November  November  November  November  November  December  December  December 
[617] December  December  December  December  December  December  December  December  December  December  December  December  December  December 
[631] December  December  December  December  December  December  December  December  December  December  December  December  December  December 
[645] January   January   January   January   January   January   January   January   January   January   January   January   January   January  
[659] January   January   January   January   January   January   January   January   January   January   January   January   January   January  
[673] January   January   January   February  February  February  February  February  February  February  February  February  February  February 
[687] February  February  February  February  February  February  February  February  February  February  February  February  February  February 
[701] February  February  February  March     March     March     March     March     March     March     March     March     March     March    
[715] March     March     March     March     March     March     March     March     March     March     March     March     March     March    
[729] March    
Levels: January February March April May June July August September October November December

Extracting date time

run the following cell to extract year, month, day

joins extraction

# substring replacement
join[,1] = gsub("\\+.*", 'Z', join[,1])

# individual extraction
year = factor(year(as.POSIXlt(join[,1])))
month = factor(months(as.POSIXlt(join[,1])),levels = month.name)
day = weekdays(as.POSIXlt(join[,1]))

# appending new indivually extracted dates
joins = cbind(join, year, month,day)
joins = joins[,c(1,5,6,7,2,3,4)]
joins

sources extraction

# substring replacement
source[,1] = gsub("\\+.*", 'Z', source[,1])

# individual extraction
year = factor(year(as.POSIXlt(source[,1])))
month = factor(months(as.POSIXlt(source[,1])),levels = month.name)
day = weekdays(as.POSIXlt(source[,1]))

# appending new indivually extracted dates
sources = cbind(source, year, month,day)
sources = sources[,c(1,5,6,7,2,3,4)]
sources
NA

leaves extraction

# substring replacement
leave[,1] = gsub("\\+.*", 'Z', leave[,1])

# individual extraction
year = factor(year(as.POSIXlt(leave[,1])))
month = factor(months(as.POSIXlt(leave[,1])),levels = month.name)
day = weekdays(as.POSIXlt(leave[,1]))

# appending new indivually extracted dates
leave
leaves = cbind(leave, year, month,day)
leaves
leaves = leaves[,c(1,4,5,6,2,3)]
leaves

messages extraction

# substring replacement
message[,1] = gsub("\\+.*", 'Z', message[,1])

# individual extraction
year = factor(year(as.POSIXlt(message[,1])))
month = factor(months(as.POSIXlt(message[,1])),levels = month.name)
day = weekdays(as.POSIXlt(message[,1]))

# appending new indivually extracted dates
messages = cbind(message, year, month,day)
messages
messages = messages[,c(1,4,5,6,2,3)]
messages

voices extraction

# substring replacement
voice[,1] = gsub("\\+.*", 'Z', voice[,1])

# individual extraction
year = factor(year(as.POSIXlt(voice[,1])))
month = factor(months(as.POSIXlt(voice[,1])),levels = month.name)
day = weekdays(as.POSIXlt(voice[,1]))

# appending new indivually extracted dates
voices = cbind(voice, year, month,day)
voices = voices[,c(1,3,4,5,2)]
voices

communicators extraction

# substring replacement
communicator[,1] = gsub("\\+.*", 'Z', communicator[,1])

# individual extraction
year = factor(year(as.POSIXlt(communicator[,1])))
month = factor(months(as.POSIXlt(communicator[,1])),levels = month.name)
day = weekdays(as.POSIXlt(communicator[,1]))
communicator

# appending new individually extracted dates
communicators = cbind(communicator, year, month,day)
communicators = communicators[,c(1,4,5,6,2,3)]
communicators$total_communicated = communicators$visitors * communicators$pct_communicated/100

Additional modifications

# marking covid and non covid months
joins$year_type = as.double(joins$year)
joins$year_type[joins$year_type == 1 ] <- "Normal"
joins$year_type[joins$year_type == 2] <- "Covid"
joins$year_type[joins$year_type == 3] <- "Covid"
joins$year_type = as.factor(joins$year_type)
joins$year_type = relevel(joins$year_type, ref = 2)
joins

leaves$year_type = as.double(leaves$year)
leaves$year_type[leaves$year_type == 1 ] <- "Normal"
leaves$year_type[leaves$year_type ==2] <- "Covid"
leaves$year_type[leaves$year_type ==3] <- "Covid"
leaves$year_type = as.factor(leaves$year_type)
leaves$year_type = relevel(leaves$year_type, ref = 2)
leaves

sources$year_type = as.double(sources$year)
sources$year_type[sources$year_type == 1 ] <- "Normal"
sources$year_type[sources$year_type ==2] <- "Covid"
sources$year_type[sources$year_type ==3] <- "Covid"
sources$year_type = as.factor(sources$year_type)
sources$year_type = relevel(sources$year_type, ref = 2)
sources

messages$year_type = as.double(messages$year)
messages$year_type[messages$year_type == 1 ] <- "Normal"
messages$year_type[messages$year_type ==2] <- "Covid"
messages$year_type[messages$year_type ==3] <- "Covid"
messages$year_type = as.factor(messages$year_type)
messages$year_type = relevel(messages$year_type, ref = 2)
messages


voices$year_type = as.double(voices$year)
voices$year_type[voices$year_type == 1 ] <- "Normal"
voices$year_type[voices$year_type ==2] <- "Covid"
voices$year_type[voices$year_type ==3] <- "Covid"
voices$year_type = as.factor(voices$year_type)
voices$year_type = relevel(voices$year_type, ref = 2)
voices

communicators$year_type = as.double(communicators$year)
communicators$year_type[communicators$year_type == 1 ] <- "Normal"
communicators$year_type[communicators$year_type ==2] <- "Covid"
communicators$year_type[communicators$year_type ==3] <- "Covid"
communicators$year_type = as.factor(communicators$year_type)
communicators$year_type = relevel(communicators$year_type, ref = 2)
communicators

data needed for investigation

historical data

joins
leaves
sources
messages
voices
communicators

last 28 days

text
voice

extracting by year

joins.2019 = subset(joins, year == 2019)
joins.2020 = subset(joins, year == 2020)
joins.2021 = subset(joins, year == 2021)

leaves.2019 = subset(leaves, year == 2019)
leaves.2020 = subset(leaves, year == 2020)
leaves.2021 = subset(leaves, year == 2021)

sources.2019 = subset(sources, year == 2019)
sources.2020 = subset(sources, year == 2020)
sources.2021 = subset(sources, year == 2021)

comm.2019 = subset(communicators, year == 2019)
comm.2020 = subset(communicators, year == 2020)
comm.2021 = subset(communicators, year == 2021)

investigating each year

2019

joins.2019
leaves.2019
sources.2019
comm.2019

2020

joins.2020
leaves.2020
sources.2020
comm.2020

2021

joins.2021
leaves.2021
sources.2021
comm.2021

Aggregating by month

2019

joins.2019
leaves.2019
comm.2019

agg_joins.2019 = aggregate(joins.2019$new_members, list(joins.2019$month), sum)
colnames(agg_joins.2019) <- c("Months", "Total New Members")
agg_leaves.2019 = aggregate(leaves.2019$leavers, list(leaves.2019$month), sum)
colnames(agg_leaves.2019) <- c("Months", "Total Leavers")
agg_comm.2019 = aggregate(comm.2019$total_communicated, list(comm.2019$month), sum)
colnames(agg_comm.2019) <- c("Months", "Total Communicated")

agg_joins.2019[order(med_joins.2019$x),]
agg_leaves.2019[order(med_leaves.2019$x),]
agg_comm.2019[order(med_comm.2019$x),]

2020

joins.2020
leaves.2020
comm.2020

agg_joins.2020 = aggregate(joins.2020$new_members, list(joins.2020$month), sum)
colnames(agg_joins.2020) <- c("Months", "Total New Members")
agg_leaves.2020 = aggregate(leaves.2020$leavers, list(leaves.2020$month), sum)
colnames(agg_leaves.2020) <- c("Months", "Total Leavers")
agg_comm.2020 = aggregate(comm.2020$total_communicated, list(comm.2020$month), sum)
colnames(agg_comm.2020) <- c("Months", "Total Communicated")


agg_joins.2020[order(med_joins.2020$x),]
agg_leaves.2020[order(med_leaves.2020$x),]
agg_comm.2020[order(med_comm.2020$x),]

2021

joins.2021
leaves.2021
comm.2021

agg_joins.2021 = aggregate(joins.2021$new_members, list(joins.2021$month), sum)
colnames(agg_joins.2021) <- c("Months", "Total New Members")
agg_leaves.2021 = aggregate(leaves.2021$leavers, list(leaves.2021$month), sum)
colnames(agg_leaves.2021) <- c("Months", "Total Leavers")
agg_comm.2021 = aggregate(comm.2021$total_communicated, list(comm.2021$month), sum)
colnames(agg_comm.2021) <- c("Months", "Total Communicated")



agg_joins.2021[order(med_joins.2021$x),]
agg_leaves.2021[order(med_leaves.2021$x),]
agg_comm.2021[order(med_comm.2021$x),]

testing aggregations

communicators
median_comm = aggregate(communicators$visitors, list(communicators$month), sum)
median_comm[order(median_comm$x),]

Aggregating by category

joins

joins
agg_joins = aggregate(new_members ~ month + year, data = joins, FUN = sum)
agg_joins

leaves

leaves
agg_leaves = aggregate(leavers ~ month + year, data = leaves, FUN = sum)
agg_leaves

experimental 3d agg

leaves
agg_leaves = aggregate(leavers ~ month + year + days_in_guild, data = leaves, FUN = sum)
agg_leaves

sources

looks really weird ignoring for now

sources
agg_sources = aggregate(discovery_joins + invites + vanity_joins ~ month + year, data = sources, FUN = sum)
agg_sources

comms

communicators
agg_comms = aggregate(total_communicated ~ month + year, data = communicators, FUN = sum)
agg_comms

visualizations

all joins

library(ggplot2)
joins

agg_joins.2019
agg_joins.2020
agg_joins.2021

agg_joins

all_joins = ggplot(data = agg_joins, mapping = aes(x = month, y = new_members, fill = year)) + xlab("Month") + ylab("Total New Members") + geom_col()+ geom_text(aes(label=new_members), position = position_stack(vjust= 0.5),
            colour = "white", size = 5) + coord_flip()
all_joins = all_joins + labs(title = "New Member Joins Across the Year")
all_joins

all leaves

leaves
agg_leaves.2019
agg_leaves.2020
agg_leaves.2021

agg_leaves

all_leaves = ggplot(data = agg_leaves, mapping = aes(x = month, y = leavers, fill = year)) + xlab("Month") + ylab("Total Leaves") + geom_col()+ geom_text(aes(label=leavers), position = position_stack(vjust= 0.5),
            colour = "white", size = 5) + coord_flip()
all_leaves = all_leaves + labs(title = "Member Leaves Across the Year")

all_leaves

all communicators

communicators

agg_comm.2019
agg_comm.2020
agg_comm.2021

agg_comms

all_comms = ggplot(data = agg_comms, mapping = aes(x = month, y = total_communicated, fill = year)) + xlab("Month") + ylab("Total Members Communicated") + geom_col()+ geom_text(aes(label=total_communicated), position = position_stack(vjust= 0.5),
            colour = "white", size = 5) + coord_flip()
all_comms = all_comms + labs(title = "All Communicating Members")
all_comms

linear models

joins linear model

joins
joins_lm = lm(new_members ~ month + year_type, data = joins)
print(summary(joins_lm))

Call:
lm(formula = new_members ~ month + year_type, data = joins)

Residuals:
   Min     1Q Median     3Q    Max 
-8.759 -2.195 -0.612  0.808 85.469 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)     1.98132    0.80555   2.460  0.01414 *  
monthFebruary   0.26401    0.96935   0.272  0.78543    
monthMarch     -0.01493    0.95690  -0.016  0.98756    
monthApril      0.60450    0.98228   0.615  0.53848    
monthMay       -0.36969    0.97461  -0.379  0.70456    
monthJune      -0.46217    0.98228  -0.471  0.63814    
monthJuly      -0.30518    0.97461  -0.313  0.75428    
monthAugust     6.54966    0.97461   6.720 3.70e-11 ***
monthSeptember  4.28783    0.98228   4.365 1.46e-05 ***
monthOctober    2.22708    0.97461   2.285  0.02260 *  
monthNovember   2.25450    0.98228   2.295  0.02201 *  
monthDecember  -0.78905    0.97461  -0.810  0.41844    
year_typeCovid  1.22836    0.44590   2.755  0.00602 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 5.283 on 716 degrees of freedom
Multiple R-squared:  0.1475,    Adjusted R-squared:  0.1332 
F-statistic: 10.32 on 12 and 716 DF,  p-value: < 2.2e-16

total messages linear model

messages
messages_lm = lm(messages ~ month + year_type, data = messages)
print(summary(messages_lm))

Call:
lm(formula = messages ~ month + year_type, data = messages)

Residuals:
    Min      1Q  Median      3Q     Max 
-533.72 -131.98  -34.98   68.19 2435.80 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)     370.7838    37.3808   9.919  < 2e-16 ***
monthFebruary     0.7405    44.9820   0.016  0.98687    
monthMarch       19.0476    44.4043   0.429  0.66808    
monthApril      153.6371    45.5819   3.371  0.00079 ***
monthMay         24.6162    45.2261   0.544  0.58641    
monthJune       -73.9795    45.5819  -1.623  0.10503    
monthJuly       -42.4322    45.2261  -0.938  0.34845    
monthAugust     210.2452    45.2261   4.649 3.98e-06 ***
monthSeptember  433.9371    45.5819   9.520  < 2e-16 ***
monthOctober    261.9549    45.2261   5.792 1.04e-08 ***
monthNovember   109.9371    45.5819   2.412  0.01612 *  
monthDecember   -79.8354    45.2261  -1.765  0.07795 .  
year_typeCovid -193.5419    20.6915  -9.354  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 245.1 on 716 degrees of freedom
Multiple R-squared:  0.369, Adjusted R-squared:  0.3584 
F-statistic: 34.89 on 12 and 716 DF,  p-value: < 2.2e-16

messages experiments

including messages_per_communicator in full model

messages
messages_lm1 = lm(messages ~ month + year_type + messages_per_communicator, data = messages)
print(summary(messages_lm1))

Call:
lm(formula = messages ~ month + year_type + messages_per_communicator, 
    data = messages)

Residuals:
    Min      1Q  Median      3Q     Max 
-794.57  -58.66    1.20   50.09 1112.68 

Coefficients:
                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)                -80.219     22.265  -3.603 0.000337 ***
monthFebruary               44.936     23.694   1.896 0.058298 .  
monthMarch                  13.590     23.369   0.582 0.561041    
monthApril                  12.429     24.209   0.513 0.607821    
monthMay                   -37.842     23.845  -1.587 0.112952    
monthJune                   -2.577     24.045  -0.107 0.914678    
monthJuly                  -33.459     23.802  -1.406 0.160241    
monthAugust                128.790     23.875   5.394 9.36e-08 ***
monthSeptember             311.849     24.154  12.911  < 2e-16 ***
monthOctober               187.593     23.863   7.861 1.40e-14 ***
monthNovember              101.338     23.989   4.224 2.71e-05 ***
monthDecember              -12.940     23.851  -0.543 0.587613    
year_typeCovid             -36.598     11.478  -3.189 0.001492 ** 
messages_per_communicator   55.895      1.292  43.247  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 129 on 715 degrees of freedom
Multiple R-squared:  0.8255,    Adjusted R-squared:  0.8223 
F-statistic: 260.2 on 13 and 715 DF,  p-value: < 2.2e-16

including messages_per_communicator in full model

messages
messages_lm2 = lm(messages_per_communicator ~ month + year_type, data = messages)
print(summary(messages_lm2))

Call:
lm(formula = messages_per_communicator ~ month + year_type, data = messages)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.5431 -2.2972 -0.7784  1.2309 28.5756 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)     8.06881    0.56882  14.185  < 2e-16 ***
monthFebruary  -0.79070    0.68449  -1.155  0.24841    
monthMarch      0.09763    0.67570   0.144  0.88515    
monthApril      2.52633    0.69362   3.642  0.00029 ***
monthMay        1.11743    0.68821   1.624  0.10489    
monthJune      -1.27745    0.69362  -1.842  0.06593 .  
monthJuly      -0.16054    0.68821  -0.233  0.81561    
monthAugust     1.45731    0.68821   2.118  0.03456 *  
monthSeptember  2.18426    0.69362   3.149  0.00171 ** 
monthOctober    1.33040    0.68821   1.933  0.05361 .  
monthNovember   0.15385    0.69362   0.222  0.82452    
monthDecember  -1.19681    0.68821  -1.739  0.08246 .  
year_typeCovid -2.80785    0.31486  -8.918  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.73 on 716 degrees of freedom
Multiple R-squared:  0.2164,    Adjusted R-squared:  0.2033 
F-statistic: 16.48 on 12 and 716 DF,  p-value: < 2.2e-16

voices linear model

voices
voices_lm = lm(speaking_minutes ~ month + year_type, data = voices)
print(summary(voices_lm))

Call:
lm(formula = speaking_minutes ~ month + year_type, data = voices)

Residuals:
    Min      1Q  Median      3Q     Max 
-928.94 -287.96  -21.33  150.04 2268.59 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)      238.42      68.62   3.475 0.000542 ***
monthFebruary     53.85      82.57   0.652 0.514493    
monthMarch       261.27      81.51   3.205 0.001409 ** 
monthApril      -217.09      83.67  -2.595 0.009665 ** 
monthMay        -269.06      83.02  -3.241 0.001246 ** 
monthJune       -225.25      83.67  -2.692 0.007265 ** 
monthJuly       -265.07      83.02  -3.193 0.001470 ** 
monthAugust      142.77      83.02   1.720 0.085914 .  
monthSeptember   474.25      83.67   5.668 2.09e-08 ***
monthOctober     463.99      83.02   5.589 3.25e-08 ***
monthNovember    256.21      83.67   3.062 0.002280 ** 
monthDecember     -9.41      83.02  -0.113 0.909785    
year_typeCovid   216.28      37.98   5.694 1.81e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 450 on 716 degrees of freedom
Multiple R-squared:  0.2877,    Adjusted R-squared:  0.2757 
F-statistic:  24.1 on 12 and 716 DF,  p-value: < 2.2e-16

communicators linear model

communicators
communicators_lm = lm(total_communicated ~ month + year_type, data = communicators)
print(summary(communicators_lm))

Call:
lm(formula = total_communicated ~ month + year_type, data = communicators)

Residuals:
    Min      1Q  Median      3Q     Max 
-39.805  -7.258  -1.258   5.628  77.195 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)     42.1266     1.9689  21.396  < 2e-16 ***
monthFebruary    4.9875     2.3693   2.105  0.03563 *  
monthMarch       2.7318     2.3388   1.168  0.24318    
monthApril       7.5910     2.4009   3.162  0.00163 ** 
monthMay        -0.3536     2.3821  -0.148  0.88203    
monthJune       -0.4757     2.4009  -0.198  0.84300    
monthJuly       -1.8698     2.3821  -0.785  0.43277    
monthAugust     20.6786     2.3821   8.681  < 2e-16 ***
monthSeptember  41.6910     2.4009  17.365  < 2e-16 ***
monthOctober    23.1141     2.3821   9.703  < 2e-16 ***
monthNovember   12.7410     2.4009   5.307 1.49e-07 ***
monthDecember   -4.6601     2.3821  -1.956  0.05082 .  
year_typeCovid  -8.8685     1.0899  -8.137 1.79e-15 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 12.91 on 716 degrees of freedom
Multiple R-squared:  0.552, Adjusted R-squared:  0.5445 
F-statistic: 73.53 on 12 and 716 DF,  p-value: < 2.2e-16

messing with top values

# dataframe_name[with(dataframe_name, order(column_name)), ]
df=voice[with(voice,order("communicators")),]
df
LS0tCnRpdGxlOiAiSWxsaW5pIEVzcG9ydHMgRW5nYWdlbWVudCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIEdyb3d0aCBhbmQgQWN0aXZhdGlvbgpgYGB7Un0Kam9pbiA9IHJlYWQuY3N2KCJndWlsZC1hY3RpdmF0aW9uLmNzdiIpCmpvaW4KCmxlYXZlID0gcmVhZC5jc3YoImd1aWxkLWxlYXZlcnMuY3N2IikKbGVhdmUKCnNvdXJjZSA9IHJlYWQuY3N2KCJndWlsZC1qb2lucy1ieS1zb3VyY2UuY3N2IikKc291cmNlCmBgYAojIEVuZ2FnZW1lbnQgYnkgY2hhbm5lbHMKYGBge3J9CnRleHQgPSByZWFkLmNzdigicG9wdWxhci10ZXh0LWNoYW5uZWxzLmNzdiIpCnRleHQKCnZvaWNlX2NoYW5uZWwgPSByZWFkLmNzdigicG9wdWxhci12b2ljZS1jaGFubmVscy5jc3YiKQp2b2ljZV9jaGFubmVsCmBgYAojIE1lc3NhZ2UgQWN0aXZpdHkKYGBge3J9Cm1lc3NhZ2UgPSByZWFkLmNzdigiZ3VpbGQtbWVzc2FnZS1hY3Rpdml0eS5jc3YiKQptZXNzYWdlCgp2b2ljZSA9IHJlYWQuY3N2KCJndWlsZC12b2ljZS1hY3Rpdml0eS5jc3YiKQp2b2ljZQoKY29tbXVuaWNhdG9yID0gcmVhZC5jc3YoImd1aWxkLWNvbW11bmljYXRvcnMuY3N2IikKY29tbXVuaWNhdG9yCmBgYAoKIyBFVEwgb24gR3Jvd3RoIGFuZCBBY3RpdmF0aW9uCiMjIG1lc3NpbmcgYXJvdW5kIHdpdGggZGF0ZSB0aW1lCiMjIyBsaWJyYXJ5CmBgYHtyfQpsaWJyYXJ5KGx1YnJpZGF0ZSkKYGBgCiMjIyBkYXRldGltZSBleGFtcGxlCkkgZ3JhYmJlZCB0aGlzIGV4YW1wbGUgZnJvbSBbYXN0cm9zdGF0cy5wc3VdKGh0dHBzOi8vYXN0cm9zdGF0aXN0aWNzLnBzdS5lZHUvc3UwNy9SL2h0bWwvYmFzZS9odG1sL2Zvcm1hdC5EYXRlLmh0bWwpCmBgYHtSfQojIyByZWFkIGluIGRhdGUvdGltZSBpbmZvIGluIGZvcm1hdCAnbS9kL3kgaDptOnMnCmRhdGVzIDwtIGMoIjAyLzI3LzkyIiwgIjAyLzI3LzkyIiwgIjAxLzE0LzkyIiwgIjAyLzI4LzkyIiwgIjAyLzAxLzkyIikKdGltZXMgPC0gYygiMjM6MDM6MjAiLCAiMjI6Mjk6NTYiLCAiMDE6MDM6MzAiLCAiMTg6MjE6MDMiLCAiMTY6NTY6MjYiKQp4IDwtIHBhc3RlKGRhdGVzLCB0aW1lcykKc3RycHRpbWUoeCwgIiVtLyVkLyV5ICVIOiVNOiVTIikKc3RycHRpbWUoeCwgIiVtLyIpCgpgYGAKIyMjIHRlc3RzIHRvIGludmVzdGlnYXRlIGhvdyB0byBleHRyYWN0IGRhdGUgdGltZQpUaGVzZSB3ZXJlIHNjdWZmZWQgdGVzdHMgSSB1c2VkIHRvIGxlYXJuIGhvdyB0byBleHRyYWN0IHRoZSBkYXRlIHRpbWUKKiB0aGUgdmFyaWFibGUgYHRlc3RgIG1hZGUgbWUgcmVhbGl6ZSByZW1vdmluZyBgKzAwOjAwYCBhbmQgcmVwbGFjaW5nIGl0IHdpdGggYSBgWmAgd291bGQgbWFrZSB0aGUgZGF0YSBpbiBhIGZvcm1hdCB0aGF0IGNhbiBiZSByZWFkIGJ5IFIKKiB0aGUgdmFyaWFibGUgYHRlc3QyYCB3YXMgbXkgYXR0ZW1wdCB0byB0cnkgZ2V0dGluZyBpdCBmb3IgYW4gZW50aXJlIGNvbHVtbgoKYGBge3J9CnRlc3QgPSAiMjAyMS0wMy0yN1QwMDowMDowMFoiCnN0cih5bWRfaG1zKHRlc3QpKQoKdGVzdDIgPSBqb2luJGludGVydmFsX3N0YXJ0X3RpbWVzdGFtcAojdGVzdDIKI3ltZF9obXMoam9pbiRpbnRlcnZhbF9zdGFydF90aW1lc3RhbXApCgojc3RycHRpbWUodGVzdDIsICIlWS0lbS0lZFQlSDolTTolU1oiKQpgYGAKV2hpbGUgcGVyZm9ybWluZyBteSB0ZXN0cywgSSBzdHJ1Z2dsZWQgdW5kZXJzdGFuZGluZyBmb3JtYXQgb2YgdGhlIGRhdGUgd2FzIGluLCBhIHNlYXJjaCBvZiBhIFsyMDIxLTAzLTI3VDAwOjAwOjAwKzAwOjAwIGRhdGF0eXBlXShodHRwczovL2R1Y2tkdWNrZ28uY29tLz9xPTIwMjEtMDMtMjdUMDAlM0EwMCUzQTAwJTJCMDAlM0EwMCtkYXRhdHlwZSZ0PWZmYWImaWE9d2ViKSBwb2ludGVkIG1lIHRvIGEgc3RhY2sgb3ZlcmZsb3cgcGFnZSB0aGF0IGhlbHBlZCBtZSBsZWFybiBtb3JlIGFib3V0IHB5dGhvbiBmdW5jdGlvbnMgW0RhdGUgVGltZSBGb3JtYXRzIGluIFB5dGhvbl0oaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTc1OTQyOTgvZGF0ZS10aW1lLWZvcm1hdHMtaW4tcHl0aG9uKS4KCiMjIyB0ZXN0aW5nIHN1YnN0cmluZyByZW1vdmFsCiogd2l0aCBhIHVuZGVyc3RhbmRpbmcgb2Ygd2hhdCBJIG5lZWRlZCB0byBtYWtlIGl0IHBvc3NpYmxlLCBJIG1vdmVkIG9uIHRvIGxlYXJuIGFib3V0IHN1YnN0cmluZyByZXBsYWNlbWVudC4gVGhpcyB0b29rIGEgbG9uZyB0aW1lIHRvIGZpZ3VyZSBvdXQgYW5kIHVuZGVyc3RhbmQuCgojIyMjIHJlbW92aW5nIHRoZSBwbHVzIHNpZ24KYSBzZWFyY2ggb2YgW1IgcmVtb3ZlIGFsbCB0ZXh0IGFmdGVyIHBsdXMgc2lnbl0oaHR0cHM6Ly9kdWNrZHVja2dvLmNvbS8/cT1SK3JlbW92ZSthbGwrdGV4dCthZnRlcitwbHVzK3NpZ24mdD1mZmFiJmlhPXdlYikgaGVscGVkIG1lIGJyZWFrIHRocm91Z2ggdGhpcyBiYXJyaWVyIEkgZm91bmQgdGhhdCB0aGlzIGFuc3dlciBvbiBzdGFja292ZXJmbG93IHdhcyBwYXJ0aWN1bGFybHkgaGVscGZ1bCBpbiByZW1vdmluZyB0aGUgYCtgIHNpZ24gW0hvdyB0byByZW1vdmUgKyAocGx1cyBzaWduKSBmcm9tIHN0cmluZyBpbiBSP10oaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM1ODA3NzM3KQoKIyMjIyByZW1vdmluZyB0aGUgcmVzdCBvZiB6ZXJvcwpJIGZvdW5kIHRoZSBmb2xsb3dpbmcgc3RhY2tvdmVyZmxvdyBhbnN3ZXIgdGhhdCBoYWQgYSBleGFtcGxlIGZvciBob3cgdG8gcmVtb3ZlIHRoZSByZXN0IG9mIGEgc3RyaW5nIFtSZW1vdmUgYWxsIHRleHQgYmVmb3JlIGNvbG9uXShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTIyOTc5OTEpCgpgYGB7cn0KZ3N1YigiXFwrLioiLCAnWicsICIyMDIxLTAzLTI3VDAwOjAwOjAwKzAwOjAwIikKYGBgCiMjIHJlbW92aW5nICswMDowMCBmcm9tIHRoZSB3aG9sZSBjb2x1bW4KdGhlc2Ugd2VyZSB0ZXN0cyBJIHJhbiB0byBhdXRvbWF0ZSB0aGlzIGZvciBhbGwgdGhlIGRhdGV0aW1lIHJvd3MKYGBge3J9CiNqb2luWzEsMV0gPSBnc3ViKCJcXCsuKiIsICdaJywgam9pblsxLDFdKQojam9pbgoKam9pblssMV0gPSBnc3ViKCJcXCsuKiIsICdaJywgam9pblssMV0pCmpvaW4KCmBgYAojIyMgc3BsaXQgdGhlIGBpbnRlcnZhbF9zdGFydF90aW1lc3RhbXBgCk9uY2UgSSBnb3QgaXQgd29ya2luZyBvbiBhIHJvdywgSSBhcHBsaWVkIHdoYXQgSSBsZWFybmVkIGFib3ZlIHRvIGV4dHJhY3QgdGhlIHllYXIsIG1vbnRoLCBhbmQgZGF5IGZyb20gdGhlIGluaXRpYWwgZGF0ZXRpbWUgb2JqZWN0CkxhdGVyIHdoZW4gSSB3YXMgZ2VuZXJhdGluZyB0aGUgYmFyIGNoYXJ0cywgSSBoYWQgaXNzdWVzIG9yZGVyaW5nIHRoZSBkYXRhIGJ5IGNhbGVuZGFyIG1vbnRocywgYSBxdWljayBzZWFyY2ggeWllbGRlZCBbU29ydGluZyBtb250aHMgaW4gUl0oaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzk3Njk3MzUpIEkgbGVhcm5lZCB0aGF0IHBhc3NpbmcgYG1vbnRoc2AgaW50byBgZmFjdG9yYCB3aXRoIHRoZSBgbGV2ZWxzID0gbW9udGgubmFtZWAgd291bGQgYWxsb3cgbWUgdG8gc29ydCBieSB0aGUgbW9udGhzCmBgYHtyfQp5ZWFyID0geWVhcihhcy5QT1NJWGx0KGpvaW4kaW50ZXJ2YWxfc3RhcnRfdGltZXN0YW1wKSkKCm1vbnRoID0gZmFjdG9yKG1vbnRocyhhcy5QT1NJWGx0KGpvaW4kaW50ZXJ2YWxfc3RhcnRfdGltZXN0YW1wKSksbGV2ZWxzID0gbW9udGgubmFtZSkKCmRheSA9IHdlZWtkYXlzKGFzLlBPU0lYbHQoam9pbiRpbnRlcnZhbF9zdGFydF90aW1lc3RhbXApKQpgYGAKCiMjIG1ha2UgdGhlIG5ldyBkYXRhZnJhbWUKQWZ0ZXIgbWFraW5nIHRoZSBzcGxpdCBkYXRhZnJhbWVzLCBJIHVzZWQgYSBjYmluZCB0byBhcHBlbmQgdGhlIGNvbHVtbnMgdG8gdGhlIG9yaWdpbmFsIGRhdGFzZXQgYW5kIHJlb3JkZXJlZCB0aGUgZGF0YXNldC4KYGBge3J9CmpvaW5zID0gY2JpbmQoam9pbiwgeWVhciwgbW9udGgsZGF5KQpqb2lucwoKam9pbnMgPSBqb2luc1ssYygxLDUsNiw3LDIsMyw0KV0Kam9pbnMKYGBgCiMjIHRlc3RpbmcgaWYgSSBjb3VsZCBjaGFuZ2UgdGhlIG1vbnRocyB0byBiZWNvbWUgYSBmYWN0b3IKYGBge3J9CiMgdGVzdCB0byBzZWUgd2hhdCB3b3VsZCBoYXBwZW4gaWYgSSBjb3VsZCBjb252ZXJ0IGEgbW9udGhzIG91dHB1dCBhcyBhIGZhY3RvcgpmYWN0b3IobW9udGhzKGFzLlBPU0lYbHQoam9pbiRpbnRlcnZhbF9zdGFydF90aW1lc3RhbXApKSxsZXZlbHMgPSBtb250aC5uYW1lKQpgYGAKCiMjIEV4dHJhY3RpbmcgZGF0ZSB0aW1lCnJ1biB0aGUgZm9sbG93aW5nIGNlbGwgdG8gZXh0cmFjdCB5ZWFyLCBtb250aCwgZGF5CgojIyMgam9pbnMgZXh0cmFjdGlvbgpgYGB7cn0KIyBzdWJzdHJpbmcgcmVwbGFjZW1lbnQKam9pblssMV0gPSBnc3ViKCJcXCsuKiIsICdaJywgam9pblssMV0pCgojIGluZGl2aWR1YWwgZXh0cmFjdGlvbgp5ZWFyID0gZmFjdG9yKHllYXIoYXMuUE9TSVhsdChqb2luWywxXSkpKQptb250aCA9IGZhY3Rvcihtb250aHMoYXMuUE9TSVhsdChqb2luWywxXSkpLGxldmVscyA9IG1vbnRoLm5hbWUpCmRheSA9IHdlZWtkYXlzKGFzLlBPU0lYbHQoam9pblssMV0pKQoKIyBhcHBlbmRpbmcgbmV3IGluZGl2dWFsbHkgZXh0cmFjdGVkIGRhdGVzCmpvaW5zID0gY2JpbmQoam9pbiwgeWVhciwgbW9udGgsZGF5KQpqb2lucyA9IGpvaW5zWyxjKDEsNSw2LDcsMiwzLDQpXQpqb2lucwpgYGAKIyMjIHNvdXJjZXMgZXh0cmFjdGlvbgpgYGB7cn0KIyBzdWJzdHJpbmcgcmVwbGFjZW1lbnQKc291cmNlWywxXSA9IGdzdWIoIlxcKy4qIiwgJ1onLCBzb3VyY2VbLDFdKQoKIyBpbmRpdmlkdWFsIGV4dHJhY3Rpb24KeWVhciA9IGZhY3Rvcih5ZWFyKGFzLlBPU0lYbHQoc291cmNlWywxXSkpKQptb250aCA9IGZhY3Rvcihtb250aHMoYXMuUE9TSVhsdChzb3VyY2VbLDFdKSksbGV2ZWxzID0gbW9udGgubmFtZSkKZGF5ID0gd2Vla2RheXMoYXMuUE9TSVhsdChzb3VyY2VbLDFdKSkKCiMgYXBwZW5kaW5nIG5ldyBpbmRpdnVhbGx5IGV4dHJhY3RlZCBkYXRlcwpzb3VyY2VzID0gY2JpbmQoc291cmNlLCB5ZWFyLCBtb250aCxkYXkpCnNvdXJjZXMgPSBzb3VyY2VzWyxjKDEsNSw2LDcsMiwzLDQpXQpzb3VyY2VzCgpgYGAKIyMjIGxlYXZlcyBleHRyYWN0aW9uCmBgYHtyfQojIHN1YnN0cmluZyByZXBsYWNlbWVudApsZWF2ZVssMV0gPSBnc3ViKCJcXCsuKiIsICdaJywgbGVhdmVbLDFdKQoKIyBpbmRpdmlkdWFsIGV4dHJhY3Rpb24KeWVhciA9IGZhY3Rvcih5ZWFyKGFzLlBPU0lYbHQobGVhdmVbLDFdKSkpCm1vbnRoID0gZmFjdG9yKG1vbnRocyhhcy5QT1NJWGx0KGxlYXZlWywxXSkpLGxldmVscyA9IG1vbnRoLm5hbWUpCmRheSA9IHdlZWtkYXlzKGFzLlBPU0lYbHQobGVhdmVbLDFdKSkKCiMgYXBwZW5kaW5nIG5ldyBpbmRpdnVhbGx5IGV4dHJhY3RlZCBkYXRlcwpsZWF2ZQpsZWF2ZXMgPSBjYmluZChsZWF2ZSwgeWVhciwgbW9udGgsZGF5KQpsZWF2ZXMKbGVhdmVzID0gbGVhdmVzWyxjKDEsNCw1LDYsMiwzKV0KbGVhdmVzCmBgYAoKIyMjIG1lc3NhZ2VzIGV4dHJhY3Rpb24KYGBge3J9CiMgc3Vic3RyaW5nIHJlcGxhY2VtZW50Cm1lc3NhZ2VbLDFdID0gZ3N1YigiXFwrLioiLCAnWicsIG1lc3NhZ2VbLDFdKQoKIyBpbmRpdmlkdWFsIGV4dHJhY3Rpb24KeWVhciA9IGZhY3Rvcih5ZWFyKGFzLlBPU0lYbHQobWVzc2FnZVssMV0pKSkKbW9udGggPSBmYWN0b3IobW9udGhzKGFzLlBPU0lYbHQobWVzc2FnZVssMV0pKSxsZXZlbHMgPSBtb250aC5uYW1lKQpkYXkgPSB3ZWVrZGF5cyhhcy5QT1NJWGx0KG1lc3NhZ2VbLDFdKSkKCiMgYXBwZW5kaW5nIG5ldyBpbmRpdnVhbGx5IGV4dHJhY3RlZCBkYXRlcwptZXNzYWdlcyA9IGNiaW5kKG1lc3NhZ2UsIHllYXIsIG1vbnRoLGRheSkKbWVzc2FnZXMKbWVzc2FnZXMgPSBtZXNzYWdlc1ssYygxLDQsNSw2LDIsMyldCm1lc3NhZ2VzCmBgYAoKIyMjIHZvaWNlcyBleHRyYWN0aW9uCmBgYHtyfQojIHN1YnN0cmluZyByZXBsYWNlbWVudAp2b2ljZVssMV0gPSBnc3ViKCJcXCsuKiIsICdaJywgdm9pY2VbLDFdKQoKIyBpbmRpdmlkdWFsIGV4dHJhY3Rpb24KeWVhciA9IGZhY3Rvcih5ZWFyKGFzLlBPU0lYbHQodm9pY2VbLDFdKSkpCm1vbnRoID0gZmFjdG9yKG1vbnRocyhhcy5QT1NJWGx0KHZvaWNlWywxXSkpLGxldmVscyA9IG1vbnRoLm5hbWUpCmRheSA9IHdlZWtkYXlzKGFzLlBPU0lYbHQodm9pY2VbLDFdKSkKCiMgYXBwZW5kaW5nIG5ldyBpbmRpdnVhbGx5IGV4dHJhY3RlZCBkYXRlcwp2b2ljZXMgPSBjYmluZCh2b2ljZSwgeWVhciwgbW9udGgsZGF5KQp2b2ljZXMgPSB2b2ljZXNbLGMoMSwzLDQsNSwyKV0Kdm9pY2VzCmBgYAojIyMgY29tbXVuaWNhdG9ycyBleHRyYWN0aW9uCmBgYHtyfQojIHN1YnN0cmluZyByZXBsYWNlbWVudApjb21tdW5pY2F0b3JbLDFdID0gZ3N1YigiXFwrLioiLCAnWicsIGNvbW11bmljYXRvclssMV0pCgojIGluZGl2aWR1YWwgZXh0cmFjdGlvbgp5ZWFyID0gZmFjdG9yKHllYXIoYXMuUE9TSVhsdChjb21tdW5pY2F0b3JbLDFdKSkpCm1vbnRoID0gZmFjdG9yKG1vbnRocyhhcy5QT1NJWGx0KGNvbW11bmljYXRvclssMV0pKSxsZXZlbHMgPSBtb250aC5uYW1lKQpkYXkgPSB3ZWVrZGF5cyhhcy5QT1NJWGx0KGNvbW11bmljYXRvclssMV0pKQpjb21tdW5pY2F0b3IKCiMgYXBwZW5kaW5nIG5ldyBpbmRpdmlkdWFsbHkgZXh0cmFjdGVkIGRhdGVzCmNvbW11bmljYXRvcnMgPSBjYmluZChjb21tdW5pY2F0b3IsIHllYXIsIG1vbnRoLGRheSkKY29tbXVuaWNhdG9ycyA9IGNvbW11bmljYXRvcnNbLGMoMSw0LDUsNiwyLDMpXQpjb21tdW5pY2F0b3JzJHRvdGFsX2NvbW11bmljYXRlZCA9IGNvbW11bmljYXRvcnMkdmlzaXRvcnMgKiBjb21tdW5pY2F0b3JzJHBjdF9jb21tdW5pY2F0ZWQvMTAwCmBgYAojIyBBZGRpdGlvbmFsIG1vZGlmaWNhdGlvbnMKYGBge3J9CiMgbWFya2luZyBjb3ZpZCBhbmQgbm9uIGNvdmlkIG1vbnRocwpqb2lucyR5ZWFyX3R5cGUgPSBhcy5kb3VibGUoam9pbnMkeWVhcikKam9pbnMkeWVhcl90eXBlW2pvaW5zJHllYXJfdHlwZSA9PSAxIF0gPC0gIk5vcm1hbCIKam9pbnMkeWVhcl90eXBlW2pvaW5zJHllYXJfdHlwZSA9PSAyXSA8LSAiQ292aWQiCmpvaW5zJHllYXJfdHlwZVtqb2lucyR5ZWFyX3R5cGUgPT0gM10gPC0gIkNvdmlkIgpqb2lucyR5ZWFyX3R5cGUgPSBhcy5mYWN0b3Ioam9pbnMkeWVhcl90eXBlKQpqb2lucyR5ZWFyX3R5cGUgPSByZWxldmVsKGpvaW5zJHllYXJfdHlwZSwgcmVmID0gMikKam9pbnMKCmxlYXZlcyR5ZWFyX3R5cGUgPSBhcy5kb3VibGUobGVhdmVzJHllYXIpCmxlYXZlcyR5ZWFyX3R5cGVbbGVhdmVzJHllYXJfdHlwZSA9PSAxIF0gPC0gIk5vcm1hbCIKbGVhdmVzJHllYXJfdHlwZVtsZWF2ZXMkeWVhcl90eXBlID09Ml0gPC0gIkNvdmlkIgpsZWF2ZXMkeWVhcl90eXBlW2xlYXZlcyR5ZWFyX3R5cGUgPT0zXSA8LSAiQ292aWQiCmxlYXZlcyR5ZWFyX3R5cGUgPSBhcy5mYWN0b3IobGVhdmVzJHllYXJfdHlwZSkKbGVhdmVzJHllYXJfdHlwZSA9IHJlbGV2ZWwobGVhdmVzJHllYXJfdHlwZSwgcmVmID0gMikKbGVhdmVzCgpzb3VyY2VzJHllYXJfdHlwZSA9IGFzLmRvdWJsZShzb3VyY2VzJHllYXIpCnNvdXJjZXMkeWVhcl90eXBlW3NvdXJjZXMkeWVhcl90eXBlID09IDEgXSA8LSAiTm9ybWFsIgpzb3VyY2VzJHllYXJfdHlwZVtzb3VyY2VzJHllYXJfdHlwZSA9PTJdIDwtICJDb3ZpZCIKc291cmNlcyR5ZWFyX3R5cGVbc291cmNlcyR5ZWFyX3R5cGUgPT0zXSA8LSAiQ292aWQiCnNvdXJjZXMkeWVhcl90eXBlID0gYXMuZmFjdG9yKHNvdXJjZXMkeWVhcl90eXBlKQpzb3VyY2VzJHllYXJfdHlwZSA9IHJlbGV2ZWwoc291cmNlcyR5ZWFyX3R5cGUsIHJlZiA9IDIpCnNvdXJjZXMKCm1lc3NhZ2VzJHllYXJfdHlwZSA9IGFzLmRvdWJsZShtZXNzYWdlcyR5ZWFyKQptZXNzYWdlcyR5ZWFyX3R5cGVbbWVzc2FnZXMkeWVhcl90eXBlID09IDEgXSA8LSAiTm9ybWFsIgptZXNzYWdlcyR5ZWFyX3R5cGVbbWVzc2FnZXMkeWVhcl90eXBlID09Ml0gPC0gIkNvdmlkIgptZXNzYWdlcyR5ZWFyX3R5cGVbbWVzc2FnZXMkeWVhcl90eXBlID09M10gPC0gIkNvdmlkIgptZXNzYWdlcyR5ZWFyX3R5cGUgPSBhcy5mYWN0b3IobWVzc2FnZXMkeWVhcl90eXBlKQptZXNzYWdlcyR5ZWFyX3R5cGUgPSByZWxldmVsKG1lc3NhZ2VzJHllYXJfdHlwZSwgcmVmID0gMikKbWVzc2FnZXMKCgp2b2ljZXMkeWVhcl90eXBlID0gYXMuZG91YmxlKHZvaWNlcyR5ZWFyKQp2b2ljZXMkeWVhcl90eXBlW3ZvaWNlcyR5ZWFyX3R5cGUgPT0gMSBdIDwtICJOb3JtYWwiCnZvaWNlcyR5ZWFyX3R5cGVbdm9pY2VzJHllYXJfdHlwZSA9PTJdIDwtICJDb3ZpZCIKdm9pY2VzJHllYXJfdHlwZVt2b2ljZXMkeWVhcl90eXBlID09M10gPC0gIkNvdmlkIgp2b2ljZXMkeWVhcl90eXBlID0gYXMuZmFjdG9yKHZvaWNlcyR5ZWFyX3R5cGUpCnZvaWNlcyR5ZWFyX3R5cGUgPSByZWxldmVsKHZvaWNlcyR5ZWFyX3R5cGUsIHJlZiA9IDIpCnZvaWNlcwoKY29tbXVuaWNhdG9ycyR5ZWFyX3R5cGUgPSBhcy5kb3VibGUoY29tbXVuaWNhdG9ycyR5ZWFyKQpjb21tdW5pY2F0b3JzJHllYXJfdHlwZVtjb21tdW5pY2F0b3JzJHllYXJfdHlwZSA9PSAxIF0gPC0gIk5vcm1hbCIKY29tbXVuaWNhdG9ycyR5ZWFyX3R5cGVbY29tbXVuaWNhdG9ycyR5ZWFyX3R5cGUgPT0yXSA8LSAiQ292aWQiCmNvbW11bmljYXRvcnMkeWVhcl90eXBlW2NvbW11bmljYXRvcnMkeWVhcl90eXBlID09M10gPC0gIkNvdmlkIgpjb21tdW5pY2F0b3JzJHllYXJfdHlwZSA9IGFzLmZhY3Rvcihjb21tdW5pY2F0b3JzJHllYXJfdHlwZSkKY29tbXVuaWNhdG9ycyR5ZWFyX3R5cGUgPSByZWxldmVsKGNvbW11bmljYXRvcnMkeWVhcl90eXBlLCByZWYgPSAyKQpjb21tdW5pY2F0b3JzCmBgYAoKCiMgZGF0YSBuZWVkZWQgZm9yIGludmVzdGlnYXRpb24KIyMgaGlzdG9yaWNhbCBkYXRhCmBgYHtyfQpqb2lucwpsZWF2ZXMKc291cmNlcwptZXNzYWdlcwp2b2ljZXMKY29tbXVuaWNhdG9ycwpgYGAKIyMgbGFzdCAyOCBkYXlzCmBgYHtyfQp0ZXh0CnZvaWNlCmBgYAojIGV4dHJhY3RpbmcgYnkgeWVhcgpgYGB7cn0Kam9pbnMuMjAxOSA9IHN1YnNldChqb2lucywgeWVhciA9PSAyMDE5KQpqb2lucy4yMDIwID0gc3Vic2V0KGpvaW5zLCB5ZWFyID09IDIwMjApCmpvaW5zLjIwMjEgPSBzdWJzZXQoam9pbnMsIHllYXIgPT0gMjAyMSkKCmxlYXZlcy4yMDE5ID0gc3Vic2V0KGxlYXZlcywgeWVhciA9PSAyMDE5KQpsZWF2ZXMuMjAyMCA9IHN1YnNldChsZWF2ZXMsIHllYXIgPT0gMjAyMCkKbGVhdmVzLjIwMjEgPSBzdWJzZXQobGVhdmVzLCB5ZWFyID09IDIwMjEpCgpzb3VyY2VzLjIwMTkgPSBzdWJzZXQoc291cmNlcywgeWVhciA9PSAyMDE5KQpzb3VyY2VzLjIwMjAgPSBzdWJzZXQoc291cmNlcywgeWVhciA9PSAyMDIwKQpzb3VyY2VzLjIwMjEgPSBzdWJzZXQoc291cmNlcywgeWVhciA9PSAyMDIxKQoKY29tbS4yMDE5ID0gc3Vic2V0KGNvbW11bmljYXRvcnMsIHllYXIgPT0gMjAxOSkKY29tbS4yMDIwID0gc3Vic2V0KGNvbW11bmljYXRvcnMsIHllYXIgPT0gMjAyMCkKY29tbS4yMDIxID0gc3Vic2V0KGNvbW11bmljYXRvcnMsIHllYXIgPT0gMjAyMSkKYGBgCgojIGludmVzdGlnYXRpbmcgZWFjaCB5ZWFyCiMjIDIwMTkKYGBge3J9CmpvaW5zLjIwMTkKbGVhdmVzLjIwMTkKc291cmNlcy4yMDE5CmNvbW0uMjAxOQpgYGAKCiMjIDIwMjAKYGBge3J9CmpvaW5zLjIwMjAKbGVhdmVzLjIwMjAKc291cmNlcy4yMDIwCmNvbW0uMjAyMApgYGAKCiMjIDIwMjEKYGBge3J9CmpvaW5zLjIwMjEKbGVhdmVzLjIwMjEKc291cmNlcy4yMDIxCmNvbW0uMjAyMQpgYGAKCiMgQWdncmVnYXRpbmcgYnkgbW9udGgKIyMgMjAxOQpgYGB7cn0Kam9pbnMuMjAxOQpsZWF2ZXMuMjAxOQpjb21tLjIwMTkKCmFnZ19qb2lucy4yMDE5ID0gYWdncmVnYXRlKGpvaW5zLjIwMTkkbmV3X21lbWJlcnMsIGxpc3Qoam9pbnMuMjAxOSRtb250aCksIHN1bSkKY29sbmFtZXMoYWdnX2pvaW5zLjIwMTkpIDwtIGMoIk1vbnRocyIsICJUb3RhbCBOZXcgTWVtYmVycyIpCmFnZ19sZWF2ZXMuMjAxOSA9IGFnZ3JlZ2F0ZShsZWF2ZXMuMjAxOSRsZWF2ZXJzLCBsaXN0KGxlYXZlcy4yMDE5JG1vbnRoKSwgc3VtKQpjb2xuYW1lcyhhZ2dfbGVhdmVzLjIwMTkpIDwtIGMoIk1vbnRocyIsICJUb3RhbCBMZWF2ZXJzIikKYWdnX2NvbW0uMjAxOSA9IGFnZ3JlZ2F0ZShjb21tLjIwMTkkdG90YWxfY29tbXVuaWNhdGVkLCBsaXN0KGNvbW0uMjAxOSRtb250aCksIHN1bSkKY29sbmFtZXMoYWdnX2NvbW0uMjAxOSkgPC0gYygiTW9udGhzIiwgIlRvdGFsIENvbW11bmljYXRlZCIpCgphZ2dfam9pbnMuMjAxOVtvcmRlcihtZWRfam9pbnMuMjAxOSR4KSxdCmFnZ19sZWF2ZXMuMjAxOVtvcmRlcihtZWRfbGVhdmVzLjIwMTkkeCksXQphZ2dfY29tbS4yMDE5W29yZGVyKG1lZF9jb21tLjIwMTkkeCksXQpgYGAKCiMjIDIwMjAKYGBge3J9CmpvaW5zLjIwMjAKbGVhdmVzLjIwMjAKY29tbS4yMDIwCgphZ2dfam9pbnMuMjAyMCA9IGFnZ3JlZ2F0ZShqb2lucy4yMDIwJG5ld19tZW1iZXJzLCBsaXN0KGpvaW5zLjIwMjAkbW9udGgpLCBzdW0pCmNvbG5hbWVzKGFnZ19qb2lucy4yMDIwKSA8LSBjKCJNb250aHMiLCAiVG90YWwgTmV3IE1lbWJlcnMiKQphZ2dfbGVhdmVzLjIwMjAgPSBhZ2dyZWdhdGUobGVhdmVzLjIwMjAkbGVhdmVycywgbGlzdChsZWF2ZXMuMjAyMCRtb250aCksIHN1bSkKY29sbmFtZXMoYWdnX2xlYXZlcy4yMDIwKSA8LSBjKCJNb250aHMiLCAiVG90YWwgTGVhdmVycyIpCmFnZ19jb21tLjIwMjAgPSBhZ2dyZWdhdGUoY29tbS4yMDIwJHRvdGFsX2NvbW11bmljYXRlZCwgbGlzdChjb21tLjIwMjAkbW9udGgpLCBzdW0pCmNvbG5hbWVzKGFnZ19jb21tLjIwMjApIDwtIGMoIk1vbnRocyIsICJUb3RhbCBDb21tdW5pY2F0ZWQiKQoKCmFnZ19qb2lucy4yMDIwW29yZGVyKG1lZF9qb2lucy4yMDIwJHgpLF0KYWdnX2xlYXZlcy4yMDIwW29yZGVyKG1lZF9sZWF2ZXMuMjAyMCR4KSxdCmFnZ19jb21tLjIwMjBbb3JkZXIobWVkX2NvbW0uMjAyMCR4KSxdCmBgYAojIyAyMDIxCmBgYHtyfQpqb2lucy4yMDIxCmxlYXZlcy4yMDIxCmNvbW0uMjAyMQoKYWdnX2pvaW5zLjIwMjEgPSBhZ2dyZWdhdGUoam9pbnMuMjAyMSRuZXdfbWVtYmVycywgbGlzdChqb2lucy4yMDIxJG1vbnRoKSwgc3VtKQpjb2xuYW1lcyhhZ2dfam9pbnMuMjAyMSkgPC0gYygiTW9udGhzIiwgIlRvdGFsIE5ldyBNZW1iZXJzIikKYWdnX2xlYXZlcy4yMDIxID0gYWdncmVnYXRlKGxlYXZlcy4yMDIxJGxlYXZlcnMsIGxpc3QobGVhdmVzLjIwMjEkbW9udGgpLCBzdW0pCmNvbG5hbWVzKGFnZ19sZWF2ZXMuMjAyMSkgPC0gYygiTW9udGhzIiwgIlRvdGFsIExlYXZlcnMiKQphZ2dfY29tbS4yMDIxID0gYWdncmVnYXRlKGNvbW0uMjAyMSR0b3RhbF9jb21tdW5pY2F0ZWQsIGxpc3QoY29tbS4yMDIxJG1vbnRoKSwgc3VtKQpjb2xuYW1lcyhhZ2dfY29tbS4yMDIxKSA8LSBjKCJNb250aHMiLCAiVG90YWwgQ29tbXVuaWNhdGVkIikKCgoKYWdnX2pvaW5zLjIwMjFbb3JkZXIobWVkX2pvaW5zLjIwMjEkeCksXQphZ2dfbGVhdmVzLjIwMjFbb3JkZXIobWVkX2xlYXZlcy4yMDIxJHgpLF0KYWdnX2NvbW0uMjAyMVtvcmRlcihtZWRfY29tbS4yMDIxJHgpLF0KYGBgCiMjIHRlc3RpbmcgYWdncmVnYXRpb25zCmBgYHtyfQpjb21tdW5pY2F0b3JzCm1lZGlhbl9jb21tID0gYWdncmVnYXRlKGNvbW11bmljYXRvcnMkdmlzaXRvcnMsIGxpc3QoY29tbXVuaWNhdG9ycyRtb250aCksIHN1bSkKbWVkaWFuX2NvbW1bb3JkZXIobWVkaWFuX2NvbW0keCksXQpgYGAKCiMgQWdncmVnYXRpbmcgYnkgY2F0ZWdvcnkKIyMgam9pbnMKYGBge3J9CmpvaW5zCmFnZ19qb2lucyA9IGFnZ3JlZ2F0ZShuZXdfbWVtYmVycyB+IG1vbnRoICsgeWVhciwgZGF0YSA9IGpvaW5zLCBGVU4gPSBzdW0pCmFnZ19qb2lucwpgYGAKIyMgbGVhdmVzCmBgYHtyfQpsZWF2ZXMKYWdnX2xlYXZlcyA9IGFnZ3JlZ2F0ZShsZWF2ZXJzIH4gbW9udGggKyB5ZWFyLCBkYXRhID0gbGVhdmVzLCBGVU4gPSBzdW0pCmFnZ19sZWF2ZXMKYGBgCgojIyMgZXhwZXJpbWVudGFsIDNkIGFnZwpgYGB7cn0KbGVhdmVzCmFnZ19sZWF2ZXMgPSBhZ2dyZWdhdGUobGVhdmVycyB+IG1vbnRoICsgeWVhciArIGRheXNfaW5fZ3VpbGQsIGRhdGEgPSBsZWF2ZXMsIEZVTiA9IHN1bSkKYWdnX2xlYXZlcwpgYGAKCiMjIHNvdXJjZXMKbG9va3MgcmVhbGx5IHdlaXJkIGlnbm9yaW5nIGZvciBub3cKYGBge3J9CnNvdXJjZXMKYWdnX3NvdXJjZXMgPSBhZ2dyZWdhdGUoZGlzY292ZXJ5X2pvaW5zICsgaW52aXRlcyArIHZhbml0eV9qb2lucyB+IG1vbnRoICsgeWVhciwgZGF0YSA9IHNvdXJjZXMsIEZVTiA9IHN1bSkKYWdnX3NvdXJjZXMKYGBgCgojIyBjb21tcwpgYGB7cn0KY29tbXVuaWNhdG9ycwphZ2dfY29tbXMgPSBhZ2dyZWdhdGUodG90YWxfY29tbXVuaWNhdGVkIH4gbW9udGggKyB5ZWFyLCBkYXRhID0gY29tbXVuaWNhdG9ycywgRlVOID0gc3VtKQphZ2dfY29tbXMKYGBgCgoKIyB2aXN1YWxpemF0aW9ucwojIyBhbGwgam9pbnMKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKam9pbnMKCmFnZ19qb2lucy4yMDE5CmFnZ19qb2lucy4yMDIwCmFnZ19qb2lucy4yMDIxCgphZ2dfam9pbnMKCmFsbF9qb2lucyA9IGdncGxvdChkYXRhID0gYWdnX2pvaW5zLCBtYXBwaW5nID0gYWVzKHggPSBtb250aCwgeSA9IG5ld19tZW1iZXJzLCBmaWxsID0geWVhcikpICsgeGxhYigiTW9udGgiKSArIHlsYWIoIlRvdGFsIE5ldyBNZW1iZXJzIikgKyBnZW9tX2NvbCgpKyBnZW9tX3RleHQoYWVzKGxhYmVsPW5ld19tZW1iZXJzKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdD0gMC41KSwKICAgICAgICAgICAgY29sb3VyID0gIndoaXRlIiwgc2l6ZSA9IDUpICsgY29vcmRfZmxpcCgpCmFsbF9qb2lucyA9IGFsbF9qb2lucyArIGxhYnModGl0bGUgPSAiTmV3IE1lbWJlciBKb2lucyBBY3Jvc3MgdGhlIFllYXIiKQphbGxfam9pbnMKYGBgCgojIyBhbGwgbGVhdmVzCmBgYHtyfQpsZWF2ZXMKYWdnX2xlYXZlcy4yMDE5CmFnZ19sZWF2ZXMuMjAyMAphZ2dfbGVhdmVzLjIwMjEKCmFnZ19sZWF2ZXMKCmFsbF9sZWF2ZXMgPSBnZ3Bsb3QoZGF0YSA9IGFnZ19sZWF2ZXMsIG1hcHBpbmcgPSBhZXMoeCA9IG1vbnRoLCB5ID0gbGVhdmVycywgZmlsbCA9IHllYXIpKSArIHhsYWIoIk1vbnRoIikgKyB5bGFiKCJUb3RhbCBMZWF2ZXMiKSArIGdlb21fY29sKCkrIGdlb21fdGV4dChhZXMobGFiZWw9bGVhdmVycyksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3Q9IDAuNSksCiAgICAgICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIHNpemUgPSA1KSArIGNvb3JkX2ZsaXAoKQphbGxfbGVhdmVzID0gYWxsX2xlYXZlcyArIGxhYnModGl0bGUgPSAiTWVtYmVyIExlYXZlcyBBY3Jvc3MgdGhlIFllYXIiKQoKYWxsX2xlYXZlcwpgYGAKIyMgYWxsIGNvbW11bmljYXRvcnMKYGBge3J9CmNvbW11bmljYXRvcnMKCmFnZ19jb21tLjIwMTkKYWdnX2NvbW0uMjAyMAphZ2dfY29tbS4yMDIxCgphZ2dfY29tbXMKCmFsbF9jb21tcyA9IGdncGxvdChkYXRhID0gYWdnX2NvbW1zLCBtYXBwaW5nID0gYWVzKHggPSBtb250aCwgeSA9IHRvdGFsX2NvbW11bmljYXRlZCwgZmlsbCA9IHllYXIpKSArIHhsYWIoIk1vbnRoIikgKyB5bGFiKCJUb3RhbCBNZW1iZXJzIENvbW11bmljYXRlZCIpICsgZ2VvbV9jb2woKSsgZ2VvbV90ZXh0KGFlcyhsYWJlbD10b3RhbF9jb21tdW5pY2F0ZWQpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0PSAwLjUpLAogICAgICAgICAgICBjb2xvdXIgPSAid2hpdGUiLCBzaXplID0gNSkgKyBjb29yZF9mbGlwKCkKYWxsX2NvbW1zID0gYWxsX2NvbW1zICsgbGFicyh0aXRsZSA9ICJBbGwgQ29tbXVuaWNhdGluZyBNZW1iZXJzIikKYWxsX2NvbW1zCmBgYAojIGxpbmVhciBtb2RlbHMKIyMgam9pbnMgbGluZWFyIG1vZGVsCmBgYHtyfQpqb2lucwpqb2luc19sbSA9IGxtKG5ld19tZW1iZXJzIH4gbW9udGggKyB5ZWFyX3R5cGUsIGRhdGEgPSBqb2lucykKcHJpbnQoc3VtbWFyeShqb2luc19sbSkpCmBgYAoKIyMgdG90YWwgbWVzc2FnZXMgbGluZWFyIG1vZGVsCmBgYHtyfQptZXNzYWdlcwptZXNzYWdlc19sbSA9IGxtKG1lc3NhZ2VzIH4gbW9udGggKyB5ZWFyX3R5cGUsIGRhdGEgPSBtZXNzYWdlcykKcHJpbnQoc3VtbWFyeShtZXNzYWdlc19sbSkpCmBgYAojIyBtZXNzYWdlcyBleHBlcmltZW50cwojIyMgaW5jbHVkaW5nIG1lc3NhZ2VzX3Blcl9jb21tdW5pY2F0b3IgaW4gZnVsbCBtb2RlbApgYGB7cn0KbWVzc2FnZXMKbWVzc2FnZXNfbG0xID0gbG0obWVzc2FnZXMgfiBtb250aCArIHllYXJfdHlwZSArIG1lc3NhZ2VzX3Blcl9jb21tdW5pY2F0b3IsIGRhdGEgPSBtZXNzYWdlcykKcHJpbnQoc3VtbWFyeShtZXNzYWdlc19sbTEpKQpgYGAKIyMjIGluY2x1ZGluZyBtZXNzYWdlc19wZXJfY29tbXVuaWNhdG9yIGluIGZ1bGwgbW9kZWwKYGBge3J9Cm1lc3NhZ2VzCm1lc3NhZ2VzX2xtMiA9IGxtKG1lc3NhZ2VzX3Blcl9jb21tdW5pY2F0b3IgfiBtb250aCArIHllYXJfdHlwZSwgZGF0YSA9IG1lc3NhZ2VzKQpwcmludChzdW1tYXJ5KG1lc3NhZ2VzX2xtMikpCmBgYAoKIyMgdm9pY2VzIGxpbmVhciBtb2RlbApgYGB7cn0Kdm9pY2VzCnZvaWNlc19sbSA9IGxtKHNwZWFraW5nX21pbnV0ZXMgfiBtb250aCArIHllYXJfdHlwZSwgZGF0YSA9IHZvaWNlcykKcHJpbnQoc3VtbWFyeSh2b2ljZXNfbG0pKQpgYGAKCiMjIGNvbW11bmljYXRvcnMgbGluZWFyIG1vZGVsCmBgYHtyfQpjb21tdW5pY2F0b3JzCmNvbW11bmljYXRvcnNfbG0gPSBsbSh0b3RhbF9jb21tdW5pY2F0ZWQgfiBtb250aCArIHllYXJfdHlwZSwgZGF0YSA9IGNvbW11bmljYXRvcnMpCnByaW50KHN1bW1hcnkoY29tbXVuaWNhdG9yc19sbSkpCmBgYAoKCiMgbWVzc2luZyB3aXRoIHRvcCB2YWx1ZXMKYGBge3J9CiMgZGF0YWZyYW1lX25hbWVbd2l0aChkYXRhZnJhbWVfbmFtZSwgb3JkZXIoY29sdW1uX25hbWUpKSwgXQpkZj12b2ljZVt3aXRoKHZvaWNlLG9yZGVyKCJjb21tdW5pY2F0b3JzIikpLF0KZGYKYGBgCg==